package com.simon.study.algorithm.shuntingyard;


import com.simon.study.algorithm.shuntingyard.SimpleLexer.Token;
import static com.simon.study.algorithm.shuntingyard.ShuntingYard.PAL;
import static com.simon.study.algorithm.shuntingyard.ShuntingYard.PAR;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 *
 * @author simon
 * @date 2022/8/28 4:23 下午
 */
public class ShuntingYardDup {

    public static void main(String[] args) {
        // String s1 = "1 + 2 * 3 + 4";
        String s1 = "0.0 + 1 + 1.2 + 0.1 + aax2 + .02 + a2b * 22/23-cc";
        toSuffix(s1);
    }


    public static void toSuffix(String txt){
        //char[] chars = txt.toCharArray();
        SimpleLexer lexer = new SimpleLexer(txt);
        lexer.parse();
        lexer.printTokens(shuntingYard(lexer.tokens));
    }


    public static List<Token> shuntingYard(List<Token> tokens){
        List<Token> postExpr = new ArrayList<>();
        Deque<Token> opstack = new ArrayDeque<>();

        for (Token token : tokens) {
            if(!operator(token)){ postExpr.add(token); }

            else if(token.prior == PAL){
                opstack.push(token);
            }else if(token.prior == PAR){
                while (!opstack.isEmpty() && opstack.peek().prior != PAL ){
                    postExpr.add(opstack.pop());
                }
                opstack.pop();
            }else{
                while (!opstack.isEmpty()
                        && opstack.peek().prior >= token.prior
                        && opstack.peek().prior != PAL ){
                    postExpr.add(opstack.pop());
                }
                opstack.push(token);
            }
        }
        while (!opstack.isEmpty()){ postExpr.add(opstack.pop()); }
        return postExpr;
    }

    public static boolean operator(Token token){
        return OPS_MAP.containsKey(token.lexeme);
    }
    public static final Map<String, Integer> OPS_MAP = new HashMap<>();
    static {
        OPS_MAP.put("+", 10);
        OPS_MAP.put("-", 10);
        OPS_MAP.put("*", 20);
        OPS_MAP.put("/", 20);
        OPS_MAP.put("(", PAL);
        OPS_MAP.put(")", PAR);
    }
}
